SPB Git forge

spb/hilmacorp

Public
1commits 1branches 0releases
29.2 MBsize
maindefault branch
20 days agolast push
TypeScript 93.3% JavaScript 4.4% CSS 2.3%
6.2 KB · 169 lines tsx
Raw Blame History
1/**2 * Author: Simon-Pierre Boucher3 * Contact: contact@spboucher.ai4 * Project: Hilmacorp.ai — Web Platform5 * File: app/[locale]/apps/page.tsx6 * Description: Apps page — web platforms (AI Risk Index, LLM Index) and the Zyquo family7 *              of native macOS applications with direct DMG downloads8 */910import type { Metadata } from "next";11import Container from "@/components/Container";12import SectionHeading from "@/components/SectionHeading";13import { getMessages, isLocale, type Locale } from "@/lib/i18n";1415export async function generateMetadata({16  params,17}: {18  params: Promise<{ locale: string }>;19}): Promise<Metadata> {20  const { locale } = await params;21  if (!isLocale(locale)) return {};22  const { meta } = getMessages(locale);23  return { title: { absolute: meta.apps.title }, description: meta.apps.description };24}2526function CheckIcon() {27  return (28    <svg29      width="16"30      height="16"31      viewBox="0 0 16 16"32      fill="none"33      aria-hidden="true"34      className="mt-0.5 shrink-0"35    >36      <path37        d="M3 8.5l3.2 3L13 4.5"38        stroke="#0b6b4a"39        strokeWidth="1.8"40        strokeLinecap="round"41        strokeLinejoin="round"42      />43    </svg>44  );45}4647export default async function AppsPage({48  params,49}: {50  params: Promise<{ locale: string }>;51}) {52  const { locale } = await params;53  const { apps } = getMessages(locale as Locale);5455  return (56    <>57      <section className="relative overflow-hidden border-b border-line">58        <div className="grid-backdrop absolute inset-0" aria-hidden="true" />59        <Container className="relative py-20 sm:py-28">60          <SectionHeading as="h1" title={apps.title} lead={apps.lead} />61        </Container>62      </section>6364      {/* Web platforms */}65      <section className="py-16 sm:py-20">66        <Container>67          <SectionHeading title={apps.webTitle} lead={apps.webLead} />68          <div className="mt-10 grid gap-6 lg:grid-cols-2">69            {apps.web.map((app) => (70              <article71                key={app.id}72                className="flex flex-col rounded-3xl border border-line bg-card p-8 shadow-sm sm:p-10"73              >74                <p className="font-mono text-xs uppercase tracking-[0.2em] text-ink-faint">75                  {app.urlLabel}76                </p>77                <h3 className="mt-3 font-display text-2xl font-semibold tracking-tight text-ink">78                  {app.name}79                </h3>80                <p className="mt-2 font-medium text-accent">{app.tagline}</p>81                <p className="mt-4 leading-relaxed text-ink-soft">{app.description}</p>82                <ul className="mt-6 grid gap-2.5">83                  {app.points.map((point) => (84                    <li key={point} className="flex items-start gap-2.5 text-sm text-ink">85                      <CheckIcon />86                      {point}87                    </li>88                  ))}89                </ul>90                <div className="mt-8 flex-1" />91                <a92                  href={app.url}93                  target="_blank"94                  rel="noopener noreferrer"95                  className="inline-flex w-fit items-center gap-2 rounded-full bg-ink px-6 py-2.5 text-sm font-medium text-paper transition-colors hover:bg-accent-strong"96                >97                  {apps.visit}98                  <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">99                    <path100                      d="M4 10L10 4M10 4H5.5M10 4v4.5"101                      stroke="currentColor"102                      strokeWidth="1.6"103                      strokeLinecap="round"104                      strokeLinejoin="round"105                    />106                  </svg>107                </a>108              </article>109            ))}110          </div>111        </Container>112      </section>113114      {/* macOS apps */}115      <section className="border-t border-line bg-paper-2 py-16 sm:py-20">116        <Container>117          <SectionHeading title={apps.macTitle} lead={apps.macLead} />118          <div className="mt-10 grid gap-6 lg:grid-cols-2">119            {apps.mac.map((app) => (120              <article121                key={app.id}122                className="flex flex-col rounded-3xl border border-line bg-card p-8 shadow-sm sm:p-10"123              >124                <p className="font-mono text-xs uppercase tracking-[0.2em] text-ink-faint">125                  {app.requires}126                </p>127                <h3 className="mt-3 font-display text-2xl font-semibold tracking-tight text-ink">128                  {app.name}129                </h3>130                <p className="mt-2 font-medium text-accent">{app.tagline}</p>131                <p className="mt-4 leading-relaxed text-ink-soft">{app.description}</p>132                <ul className="mt-6 grid gap-2.5">133                  {app.points.map((point) => (134                    <li key={point} className="flex items-start gap-2.5 text-sm text-ink">135                      <CheckIcon />136                      {point}137                    </li>138                  ))}139                </ul>140                <div className="mt-8 flex-1" />141                <div className="flex flex-wrap items-center gap-4">142                  <a143                    href={`/downloads/${app.file}`}144                    download145                    className="inline-flex items-center gap-2 rounded-full bg-ink px-6 py-2.5 text-sm font-medium text-paper transition-colors hover:bg-accent-strong"146                  >147                    <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">148                      <path149                        d="M7 1.5v8m0 0L3.8 6.3M7 9.5l3.2-3.2M2 12.5h10"150                        stroke="currentColor"151                        strokeWidth="1.6"152                        strokeLinecap="round"153                        strokeLinejoin="round"154                      />155                    </svg>156                    {apps.download}157                  </a>158                  <span className="font-mono text-xs text-ink-faint">{app.size}</span>159                </div>160              </article>161            ))}162          </div>163          <p className="mt-10 text-sm text-ink-faint">{apps.macNote}</p>164        </Container>165      </section>166    </>167  );168}169